package com.zdb.demo.design.pattern.creational.singleton;

import java.io.*;
import java.lang.reflect.Constructor;

public class Test {
    public static void main(String[] args) {
        testSerializable();
    }

    public static void testSerializable() {
        SerializableSingleton serializableSingleton = SerializableSingleton.getInstance();
        System.out.println("1--- \t" + serializableSingleton);

        try {
            String filePath = "E:\\logs\\tmp\\oo_test";
            clearFile(filePath);
            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath));
            os.writeObject(serializableSingleton);
            os.flush();
            os.close();

            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
            SerializableSingleton serializableSingleton2 = (SerializableSingleton)ois.readObject();

            System.out.println("2--- \t" + serializableSingleton2);
            System.out.println(serializableSingleton2 == serializableSingleton);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void clearFile(String filePath) {
        File file = new File(filePath);
        if(file.exists()) {
            file.delete();
        }
    }

    @org.junit.Test
    public void testReflect() throws Exception {
        ReflectHungrySingleton instance = ReflectHungrySingleton.getInstance();
        Constructor con = ReflectHungrySingleton.class.getDeclaredConstructor();
        con.setAccessible(true);
        ReflectHungrySingleton newInstance = (ReflectHungrySingleton) con.newInstance();
        System.out.println(instance);
        System.out.println(newInstance);
        System.out.println(instance == newInstance);
    }

    @org.junit.Test
    public void testReflectMutiThread() throws Exception {

        new Thread(() -> {
            System.out.println("---- begin ----");
            ReflectHungrySingleton instance = ReflectHungrySingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + "\t" + instance);
        }).start();

        new Thread(() -> {
            System.out.println("---- begin ----");
            Constructor con = null;
            try {
                con = ReflectHungrySingleton.class.getDeclaredConstructor();
                con.setAccessible(true);
                ReflectHungrySingleton newInstance = (ReflectHungrySingleton) con.newInstance();
                System.out.println(newInstance);
                System.out.println(Thread.currentThread().getName() + "\t" + newInstance);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        System.out.println("--------------");
    }

    @org.junit.Test
    public void testReflectStaticInnerClassSingleton() throws Exception {
        ReflectStaticInnerClassSingleton.test();
//        ReflectStaticInnerClassSingleton instance = ReflectStaticInnerClassSingleton.getInstance();
        ReflectStaticInnerClassSingleton instance = ReflectStaticInnerClassSingleton.getInstance();
        Constructor con = ReflectStaticInnerClassSingleton.class.getDeclaredConstructor();
        con.setAccessible(true);
        ReflectStaticInnerClassSingleton newInstance = (ReflectStaticInnerClassSingleton) con.newInstance();
        System.out.println(instance);
        System.out.println(newInstance);
        System.out.println(instance == newInstance);
    }

    @org.junit.Test
    public void testEnumInstance() throws Exception {
        EnumInstance instance = EnumInstance.INSTANCE;
        instance.printTest();
    }
}
